package com.d3works.apps.businessproject.service;

import com.d3works.apps.account.db.Invoice;
import com.d3works.apps.account.db.repo.InvoicePaymentRepository;
import com.d3works.apps.account.service.config.AccountConfigService;
import com.d3works.apps.account.service.invoice.InvoiceService;
import com.d3works.apps.account.service.payment.invoice.payment.InvoicePaymentCreateService;
import com.d3works.apps.base.service.UnitConversionService;
import com.d3works.apps.base.service.app.AppBaseService;
import com.d3works.apps.businessproject.db.InvoicingProject;
import com.d3works.apps.businessproject.db.repo.InvoicingProjectRepository;
import com.d3works.apps.businessproject.service.app.AppBusinessProjectService;
import com.d3works.apps.hr.db.ExpenseLine;
import com.d3works.apps.hr.db.TimesheetLine;
import com.d3works.apps.hr.db.repo.TimesheetLineRepository;
import com.d3works.apps.project.db.ProjectTask;
import com.d3works.apps.purchase.db.PurchaseOrderLine;
import com.d3works.apps.purchase.db.repo.PurchaseOrderRepository;
import com.d3works.apps.sale.db.SaleOrderLine;
import com.d3works.apps.sale.db.repo.SaleOrderRepository;
import com.d3works.apps.stock.db.repo.StockMoveLineRepository;
import com.d3works.apps.supplychain.service.AccountingSituationSupplychainService;
import com.d3works.apps.supplychain.service.PurchaseOrderInvoiceService;
import com.d3works.apps.supplychain.service.SaleOrderInvoiceService;
import com.d3works.apps.supplychain.service.StockMoveInvoiceService;
import com.d3works.apps.supplychain.service.app.AppSupplychainService;
import com.d3works.apps.supplychain.service.config.SupplyChainConfigService;
import com.d3works.apps.supplychain.service.workflow.WorkflowVentilationServiceSupplychainImpl;
import com.d3works.exception.D3worksException;
import com.d3works.inject.Beans;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;

public class WorkflowVentilationProjectServiceImpl
    extends WorkflowVentilationServiceSupplychainImpl {

  private InvoicingProjectRepository invoicingProjectRepo;

  private TimesheetLineRepository timesheetLineRepo;

  @Inject
  public WorkflowVentilationProjectServiceImpl(
      AccountConfigService accountConfigService,
      InvoicePaymentRepository invoicePaymentRepo,
      InvoicePaymentCreateService invoicePaymentCreateService,
      InvoiceService invoiceService,
      SaleOrderInvoiceService saleOrderInvoiceService,
      PurchaseOrderInvoiceService purchaseOrderInvoiceService,
      SaleOrderRepository saleOrderRepository,
      PurchaseOrderRepository purchaseOrderRepository,
      AccountingSituationSupplychainService accountingSituationSupplychainService,
      AppSupplychainService appSupplychainService,
      InvoicingProjectRepository invoicingProjectRepo,
      TimesheetLineRepository timesheetLineRepo,
      StockMoveInvoiceService stockMoveInvoiceService,
      UnitConversionService unitConversionService,
      AppBaseService appBaseService,
      SupplyChainConfigService supplyChainConfigService,
      StockMoveLineRepository stockMoveLineRepository) {
    super(
        accountConfigService,
        invoicePaymentRepo,
        invoicePaymentCreateService,
        invoiceService,
        saleOrderInvoiceService,
        purchaseOrderInvoiceService,
        saleOrderRepository,
        purchaseOrderRepository,
        accountingSituationSupplychainService,
        appSupplychainService,
        stockMoveInvoiceService,
        unitConversionService,
        appBaseService,
        supplyChainConfigService,
        stockMoveLineRepository);
    this.invoicingProjectRepo = invoicingProjectRepo;
    this.timesheetLineRepo = timesheetLineRepo;
  }

  @Override
  @Transactional(rollbackOn = {Exception.class})
  public void afterVentilation(Invoice invoice) throws D3worksException {
    super.afterVentilation(invoice);

    if (!Beans.get(AppBusinessProjectService.class).isApp("business-project")) {
      return;
    }

    InvoicingProject invoicingProject =
        invoicingProjectRepo.all().filter("self.invoice.id = ?", invoice.getId()).fetchOne();

    if (invoicingProject != null) {
      for (SaleOrderLine saleOrderLine : invoicingProject.getSaleOrderLineSet()) {
        saleOrderLine.setInvoiced(true);
      }
      for (PurchaseOrderLine purchaseOrderLine : invoicingProject.getPurchaseOrderLineSet()) {
        purchaseOrderLine.setInvoiced(true);
      }
      for (TimesheetLine timesheetLine : invoicingProject.getLogTimesSet()) {
        timesheetLine.setInvoiced(true);

        if (timesheetLine.getProjectTask() == null) {
          continue;
        }

        timesheetLine
            .getProjectTask()
            .setInvoiced(this.checkInvoicedTimesheetLines(timesheetLine.getProjectTask()));
      }
      for (ExpenseLine expenseLine : invoicingProject.getExpenseLineSet()) {
        expenseLine.setInvoiced(true);
      }
      for (ProjectTask projectTask : invoicingProject.getProjectTaskSet()) {
        projectTask.setInvoiced(true);
      }

      invoicingProject.setStatusSelect(InvoicingProjectRepository.STATUS_VENTILATED);
      invoicingProjectRepo.save(invoicingProject);
    }
  }

  private boolean checkInvoicedTimesheetLines(ProjectTask projectTask) {

    long timesheetLineCnt =
        timesheetLineRepo
            .all()
            .filter("self.projectTask.id = ?1 AND self.invoiced = ?2", projectTask.getId(), false)
            .count();

    return timesheetLineCnt == 0;
  }
}
